/*************************************************************************
                           MsgQueue  -  description
                             -------------------
    début                : 27 janv. 2012
    copyright            : (C) 2012 par ubunt11
*************************************************************************/

//---------- Interface de la classe <MsgQueue> (fichier MsgQueue.h) ------
#if ! defined ( MSG_QUEUE_H )
#define MSG_QUEUE_H

//--------------------------------------------------- Interfaces utilisées
#include <queue>
#include <pthread.h>

//------------------------------------------------------------- Constantes 

//------------------------------------------------------------------ Types 

//------------------------------------------------------------------------ 
// Rôle de la classe <MsgQueue>
//
//
//------------------------------------------------------------------------ 

template<typename T>
class MsgQueue
{
	private:
		std::queue<T> the_queue;
		mutable pthread_mutex_t lockData;
		pthread_cond_t notify;
	public:

		MsgQueue() {
			if (pthread_mutex_init(&lockData, NULL) != 0) {
				//error
			}
			if (pthread_cond_init(&notify, NULL) != 0) {
				//error
			}
		}

		~MsgQueue() {
			pthread_mutex_destroy(&lockData);
			pthread_cond_destroy(&notify);
		}

		void push(T const& data)
		{
			pthread_mutex_lock(&lockData);
			the_queue.push(data);
			pthread_mutex_unlock(&lockData);
			pthread_cond_signal(&notify);
		}

		bool isEmpty() const
		{
			bool empty;
			pthread_mutex_lock(&lockData);
			empty = the_queue.empty();
			pthread_mutex_unlock(&lockData);
			return empty;
		}

		bool try_pop(T& popped_value)
		{
			bool cr = true;
			pthread_mutex_lock(&lockData);
			if(the_queue.empty())
			{
				cr = false;
			} else {
				popped_value=the_queue.front();
				the_queue.pop();
			}
			pthread_mutex_unlock(&lockData);
			return cr;
		}

		void wait_and_pop(T& popped_value)
		{
			pthread_mutex_lock(&lockData);
			while(the_queue.empty())
			{
				pthread_cond_wait(&notify, &lockData);
			}
			popped_value=the_queue.front();
			the_queue.pop();
			pthread_mutex_unlock(&lockData);
		}

};

//----------------------------------------- Types dépendants de <MsgQueue>

#endif // MSG_QUEUE_H
